<!--
 * @Description: kgBuilder
 * @Author: tanc
 * @Date: 2021-12-26 16:50:07
 * @LastEditors: your name
 * @LastEditTime: 2021-12-28 23:03:15
-->
<template>
  <div class="mind-box" @mousedown="boxMousedown">
    <!-- 左侧 -->
    <el-scrollbar class="mind-l">
      <div class="ml-m">
        <h2 class="ml-ht">图谱列表</h2>
        <div class="ml-a-box" style="min-height:280px">
          <el-button
            type="info"
            style="margin: 2px 0 4px 2px;"
            plain
            size="small"
            @click="createDomain"
            >新建图谱</el-button
          >
          <a
            @click="matchDomainGraph(m, $event)"
            v-for="m in pageModel.nodeList"
            href="javascript:void(0)"
          >
            <el-tag
              v-if="m.commend == 0"
              closable
              style="margin:2px"
              @close="deleteDomain(m.id, m.name)"
              >{{ m.name }}</el-tag
            >
          </a>
          <el-button
            v-if="pageModel.pageIndex < pageModel.totalPage"
            type="info"
            style="margin: 2px 0 4px 2px;"
            plain
            size="small"
            @click="getMoreDomain"
            >加载更多</el-button
          >
        </div>
        <h2 class="ml-ht">精选图谱</h2>
        <div class="ml-a-box" style="min-height:280px">
          <a
            @click="matchDomainGraph(m, $event)"
            v-for="m in recommendPageModel.nodeList"
            href="javascript:void(0)"
          >
            <el-tag style="margin:2px">{{ m.name }}</el-tag>
          </a>
          <el-button
            v-if="recommendPageModel.pageIndex < recommendPageModel.totalPage"
            type="info"
            style="margin: 2px 0 4px 2px;"
            plain
            size="small"
            @click="getMoreDomain"
            >加载更多</el-button
          >
        </div>
        <div id="follow-us" class="guanzhu" style="padding: 20px;">
          <h2 class="hometitle">交流</h2>
          <ul>
            <li class="wx">
              <img
                src="https://img-blog.csdnimg.cn/20201003145558813.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BveGlhb21lbmcxODc=,size_16,color_FFFFFF,t_70#pic_center"
              />
            </li>
          </ul>
        </div>
      </div>
    </el-scrollbar>
    <!-- 左侧over -->
    <!-- 右侧 -->
    <div class="mind-con">
      <!-- 头部 -->
      <div class="mind-top clearfix">
        <div class="fl" style="padding: 5px;display: flex">
          <div class="search">
            <el-button @click="getDomainGraph(0)">
              <svg class="icon" aria-hidden="true">
                <use xlink:href="#icon-search"></use>
              </svg>
            </el-button>
            <el-input
              placeholder="请输入关键词"
              v-model="nodeName"
              @keyup.enter.native="getDomainGraph"
            ></el-input>
          </div>
          <span>
            <span class="dibmr">
              <span>显示节点个数:</span>
              <a
                v-for="(m, index) in pageSizeList"
                @click="setMatchSize(m, this)"
                :title="m.size"
                href="javascript:void(0)"
                :class="[m.isActive ? 'sd-active' : '', 'sd']"
                >{{ m.size }}</a
              >
            </span>
          </span>
        </div>
        <div class="fr">
          <a href="javascript:void(0)" @click="cypherJson" class="svg-a-sm">
            <i class="el-icon-tickets">显示json</i>
          </a>
          <a href="javascript:void(0)" @click="showCypher" class="svg-a-sm">
            <i class="el-icon-caret-right">执行Cypher</i>
          </a>
          <a href="javascript:void(0)" @click="updateGraph" class="svg-a-sm">
            <svg class="icon" aria-hidden="true">
              <use xlink:href="#icon-shuaxin"></use></svg
            >刷新
          </a>
          <a
            href="javascript:void(0)"
            @click="requestFullScreen"
            class="svg-a-sm"
          >
            <svg class="icon" aria-hidden="true">
              <use xlink:href="#icon-quanp"></use></svg
            >全屏
          </a>
          <el-dropdown @command="operateCommand">
            <el-button type="primary">
              操作<i class="el-icon-arrow-down el-icon--right"></i>
            </el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item command="image">导出图片</el-dropdown-item>
              <el-dropdown-item command="import">导入</el-dropdown-item>
              <el-dropdown-item command="export">导出</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </div>
      <div class="cypher_toolbar clearfix" v-show="cypherTextShow">
        <div style="width: 80%;float: left">
          <el-input
            type="textarea"
            :rows="2"
            placeholder="请输入Cypher"
            v-model="cypherText"
          >
          </el-input>
        </div>
        <div style="padding: 7px;">
          <el-button
            type="success"
            @click="cypherRun"
            style="margin-left: 15px;"
            icon="el-icon-caret-right"
            plain
            >执行</el-button
          >
        </div>
      </div>
      <!-- 头部over -->
      <!-- 中部 -->
      <el-scrollbar class="mind-cen" id="graphcontainerdiv">
        <div id="nodeDetail" class="node_detail">
          <h5>详细数据</h5>
          <span class="node_pd" v-for="(m, k) in nodeDetail"
            >{{ k }}:{{ m }}</span
          >
        </div>
        <div
          id="graphContainer"
          class="graphContainer"
          @click="initContainerLeftClick"
          @contextmenu.prevent="initContainerRightClick"
        ></div>
      </el-scrollbar>
      <!-- 中部over -->
      <div class="svg-set-box"></div>
      <!-- 底部 -->
      <el-dialog title="导入图谱" :visible.sync="dialogFormVisible" width="30%">
        <el-form>
          <el-form-item label="tips" label-width="120px">
            <div>
              <img style="width: 300px;" :src="uploadTips.img" />
              <span style="margin: auto;">{{ uploadTips.tips }}</span>
            </div>
          </el-form-item>
          <el-form-item label="类型" label-width="120px">
            <el-radio-group v-model="uploadParam.type">
              <el-radio
                @change="radioClick(m)"
                :key="m.id"
                v-for="m in uploadTipsArr"
                :label="m.type"
                >{{ m.name }}</el-radio
              >
            </el-radio-group>
          </el-form-item>
          <el-form-item label="图谱领域" label-width="120px">
            <el-autocomplete
              style="width:100%"
              v-model="uploadParam.domain"
              placeholder="请输入内容"
            >
            </el-autocomplete>
          </el-form-item>
          <el-form-item label="选择文件" label-width="120px">
            <el-upload
              class=""
              :headers="headers"
              ref="upload"
              :action="uploadUrl"
              accept=".csv,.xls,.xlsx"
              :show-file-list="true"
              :data="uploadParam"
              :on-success="csvSuccess"
              :auto-upload="false"
            >
              <el-button
                slot="trigger"
                class="btn-bo"
                style="padding: 12px 24px;margin-bottom: 0px;"
              >
                <svg class="icon" aria-hidden="true">
                  <use xlink:href="#icon-daoru"></use>
                </svg>
                选择文件
              </el-button>
            </el-upload>
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button @click="dialogFormVisible = false">取 消</el-button>
          <el-button type="primary" @click="submitUpload">确 定</el-button>
        </div>
      </el-dialog>
      <el-dialog
        title="导出图谱csv"
        :visible.sync="exportFormVisible"
        width="30%"
      >
        <el-form>
          <el-form-item label="图谱领域" label-width="120px">
            <el-autocomplete
              style="width:100%"
              v-model="uploadParam.domain"
              placeholder="请输入内容"
              ><!--:fetch-suggestions="querySearch"-->
            </el-autocomplete>
          </el-form-item>
          <el-button type="primary" @click="exportCsv">确 定</el-button>
        </el-form>
      </el-dialog>
      <el-dialog
        id="editform"
        title="属性编辑"
        :visible.sync="isEdit"
        width="30%"
      >
        <el-tabs
          type="card"
          tab-position="top"
          v-model="propActiveName"
          @tab-click="propHandleClick"
          style="margin: 10px"
        >
          <el-tab-pane label="属性编辑" name="propEdit">
            <el-form :model="graphNode">
              <el-form-item label="节点名称" label-width="120px">
                <el-input
                  v-model="graphNode.name"
                  style="width:324px"
                ></el-input>
              </el-form-item>
              <el-form-item label="选择颜色" label-width="120px">
                <el-color-picker
                  id="colorpicker"
                  v-model="graphNode.color"
                  :predefine="predefineColors"
                >
                </el-color-picker>
              </el-form-item>
              <el-form-item label="节点半径" label-width="120px">
                <el-slider
                  v-model="graphNode.r"
                  style="width:324px"
                ></el-slider>
              </el-form-item>
            </el-form>
          </el-tab-pane>
          <el-tab-pane label="添加图片" name="propImage">
            <el-form>
              <el-form-item label="本地上传" label-width="120px">
                <el-upload
                  class=""
                  :headers="headers"
                  name="file"
                  ref="upload"
                  :action="uploadImageUrl"
                  accept=".jpg,.png"
                  multiple
                  :show-file-list="false"
                  :data="uploadImageParam"
                  :on-success="uploadSuccess"
                  :auto-upload="true"
                >
                  <el-button slot="trigger" size="small" type="primary"
                    >选择</el-button
                  >
                </el-upload>
              </el-form-item>
              <el-form-item label="网络地址" label-width="120px">
                <el-input v-model="netImageUrl" style="width: 60%"></el-input>
                <a href="javascript:void(0)" @click="addNetImage" class="cg">
                  <svg class="icon" aria-hidden="true">
                    <use xlink:href="#icon-add-s"></use>
                  </svg>
                </a>
              </el-form-item>
              <el-form-item label="已选图片" label-width="120px">
                <ul class="el-upload-list el-upload-list--picture-card">
                  <li
                    v-for="item in nodeImageList"
                    class="el-upload-list__item is-success"
                  >
                    <img
                      :src="imageUrlFormat(item)"
                      alt=""
                      class="el-upload-list__item-thumbnail"
                    />
                    <label class="el-upload-list__item-status-label">
                      <i class="el-icon-upload-success el-icon-check"></i>
                    </label>
                    <i
                      class="el-icon-close"
                      @click="imageHandleRemove(item)"
                    ></i>
                    <span class="el-upload-list__item-actions">
                      <span class="el-upload-list__item-preview">
                        <i
                          class="el-icon-zoom-in"
                          @click="handlePictureCardPreview(item)"
                        ></i>
                      </span>
                      <span class="el-upload-list__item-delete">
                        <i
                          class="el-icon-delete"
                          @click="imageHandleRemove(item)"
                        ></i>
                      </span>
                    </span>
                  </li>
                </ul>
              </el-form-item>
            </el-form>
          </el-tab-pane>
          <el-tab-pane label="添加描述" name="richTextEdit">
            <div
              ref="editorToolbar"
              id="editorToolbar"
              class="wange-toolbar"
            ></div>
            <div
              ref="editorContent"
              id="editorContent"
              class="wangeditor-form"
            ></div>
          </el-tab-pane>
        </el-tabs>
        <div slot="footer" class="dialog-footer">
          <el-button
            v-show="propActiveName == 'propImage'"
            type="primary"
            @click="saveNodeImage"
            class="btn-line cur"
            >保存</el-button
          >
          <el-button
            v-show="propActiveName == 'richTextEdit'"
            @click="saveNodeContent"
            type="primary"
            class="btn-line cur"
            >保存</el-button
          >
          <el-button
            v-show="propActiveName == 'propEdit' && graphNode.uuid != 0"
            type="primary"
            @click="createNode"
            >更新</el-button
          >
          <el-button
            v-show="propActiveName == 'propEdit' && graphNode.uuid == 0"
            type="primary"
            @click="createNode"
            >创建</el-button
          >
          <el-button @click="resetSubmit">取消</el-button>
        </div>
      </el-dialog>
      <el-dialog
        id="batchcreateform"
        :title="operateNameFormat(operateType)"
        :visible.sync="isBatchCreate"
        width="30%"
      >
        <div v-show="operateType == 1" class="mb-l">添加同级</div>
        <div v-show="operateType == 2" class="mb-l">添加下级</div>
        <div v-show="operateType == 3" class="mb-l">批量添加</div>
        <div v-show="operateType == 4" class="mb-l">段落识别</div>
        <div class="mb-r">
          <div v-show="operateType != 2" class="mb-m">
            <div class="mb-label">源节点名称</div>
            <div class="mb-con">
              <el-input v-model="batchCreate.sourceNodeName"></el-input>
              <span v-show="operateType == 3" class="mb-label"
                >（只能添加一个）</span
              >
              <span v-show="operateType == 1" class="mb-label"
                >（多个以英文逗号隔开）</span
              >
            </div>
            <div class="mb-label" v-show="operateType !== 1">关系</div>
            <div class="mb-con" v-show="operateType !== 1">
              <el-input v-model="batchCreate.relation"></el-input>
              <div class="mb-label">（只能添加一个）</div>
            </div>
          </div>
          <div v-show="operateType != 1" class="mb-m">
            <div class="mb-label">子节点名称</div>
            <div class="mb-con">
              <el-input v-model="batchCreate.targetNodeNames"></el-input>
              <span class="mb-label " v-show="operateType == 3"
                >（多个以英文逗号隔开,可不填）</span
              >
              <span class="mb-label " v-show="operateType == 2"
                >（多个以英文逗号隔开）</span
              >
            </div>
          </div>
          <div class="mb-m tc">
            <el-button
              v-show="operateType == 1"
              type="primary"
              @click="batchCreateSameNode"
              >确定</el-button
            >
            <el-button
              v-show="operateType == 2"
              type="primary"
              @click="batchCreateChildNode"
              >确定</el-button
            >
            <el-button
              v-show="operateType == 3"
              type="primary"
              @click="batchCreateNode"
              >确定</el-button
            >
            <el-button @click="resetSubmit">取消</el-button>
          </div>
        </div>
      </el-dialog>
      <!-- 底部over -->
    </div>
    <!-- 右侧over -->
    <!-- 空白处右键 -->
    <div>
        <menu-blank
          ref="menu_blank"
          @btnAddSingle="btnAddSingle"
          @btnQuickAddNode="btnQuickAddNode"
        ></menu-blank>
      </div>
    <!-- 连线按钮组 -->
    <div>
        <menu-link
          ref="menu_link"
          @updateLinkName="updateLinkName"
          @deleteLink="deleteLink"
        ></menu-link>
      </div>

    <!-- 富文本展示 -->
    <div id="richContainer" style="display: none;width: 400px">
      <div
        class="mind-fj-box"
        v-show="showImageList.length > 0 || editorContent != ''"
      >
        <div class="mind-carousel" v-show="showImageList.length > 0">
          <el-carousel height="197px" :interval="2000" arrow="always">
            <el-carousel-item v-for="item in showImageList" :key="item.ID">
              <div class="carous-img">
                <img :src="item.fileName" alt="" />
              </div>
            </el-carousel-item>
          </el-carousel>
        </div>
        <el-scrollbar v-show="editorContent != ''" class="mind-fj-p">
          <p v-html="editorContent"></p>
        </el-scrollbar>
      </div>
    </div>
  </div>
</template>
<script>
import _ from "lodash";
import * as d3 from "d3";
import $ from "jquery";
import { kgBuilderApi } from "@/api";
import MenuBlank from "@/views/kgbuilder/components/menu_blank";
import MenuLink from "@/views/kgbuilder/components/menu_link";
export default {
  name: "kgBuilder",
  components: {
    MenuBlank,
    MenuLink
  },
  data() {
    return {
      svg: null,
      timer: null,
      editor: null,
      simulation: null,
      linkGroup: null,
      linkTextGroup: null,
      nodeGroup: null,
      nodeTextGroup: null,
      nodeSymbolGroup: null,
      nodeButtonGroup: null,
      nodeButtonAction: "",
      tooltip: null,
      tipsShow: true,
      txx: {},
      tyy: {},
      nodeDetail: null,
      pageSizeList: [
        { size: 100, isActive: true },
        { size: 500, isActive: false },
        { size: 1000, isActive: false },
        { size: 2000, isActive: false }
      ],
      colorList: [
        "#ff8373",
        "#f9c62c",
        "#a5ca34",
        "#6fce7a",
        "#70d3bd",
        "#ea91b0"
      ],
      color5: "#ff4500",
      predefineColors: [
        "#ff4500",
        "#ff8c00",
        "#90ee90",
        "#00ced1",
        "#1e90ff",
        "#c71585"
      ],
      defaultCr: 30,
      activeName: "",
      dataConfigActive: "",
      queryWords: "",
      operateType: 0,
      isEdit: false,
      isAddNode: false,
      isAddLink: false,
      isDeleteLink: false,
      isBatchCreate: false,
      selectNodeId: 0,
      selectNodeName: "",
      selectSourceNodeId: 0,
      selectTargetNodeId: 0,
      sourceNodeX1: 0,
      sourceNodeY1: 0,
      mouseX: 0,
      mouseY: 0,
      domain: "",
      domainId: 0,
      nodeName: "",
      pageSize: 100,
      cypherText: "",
      cypherTextShow: false,
      jsonShow: false,
      propActiveName: "propEdit",
      contentActiveName: "propImage",
      uploadImageUrl: "qiniu/upload",
      uploadImageParam: {},
      nodeImageList: [],
      netImageUrl: "",
      dialogImageVisible: false,
      dialogImageUrl: "",
      showImageList: [],
      editorContent: "",
      selectNode: {
        name: "",
        count: 0
      },
      pageModel: {
        pageIndex: 1,
        pageSize: 10,
        totalCount: 0,
        totalPage: 0,
        nodeList: []
      },
      recommendPageModel: {
        pageIndex: 1,
        pageSize: 10,
        totalCount: 0,
        totalPage: 0,
        nodeList: []
      },
      graph: {
        nodes: [],
        links: []
      },
      batchCreate: {
        sourceNodeName: "",
        targetNodeNames: "",
        relation: ""
      },
      graphNode: {
        uuid: 0,
        name: "",
        color: "ff4500",
        r: 30,
        x: "",
        y: ""
      },
      uploadParam: { domain: "", type: 0 },
      uploadTips: {
        tips: "csv导入，注意字符集为utf-8无bom格式，三元组结构:节点-节点-关系",
        img: ""
      },
      uploadTipsArr: [
        {
          tips:
            "csv导入，注意字符集为utf-8无bom格式，三元组结构:节点-节点-关系",
          name: "三元组",
          img: "",
          type: 0
        },
        {
          tips:
            "支持合并单元格，设置颜色，设置关系需在节点后以###拼接，只识别一组关系",
          name: "单元格树",
          img: "http://file.miaoleyan.com/image-20211114183140256.png",
          type: 1
        }
      ],
      domainLabels: [],
      dialogFormVisible: false,
      exportFormVisible: false,
      headers: {},
      uploadUrl: "importGraph"
    };
  },
  filters: {
    labelFormat: function(value) {
      let domain = value.substring(1, value.length - 1);
      return domain;
    }
  },
  mounted() {
    this.$nextTick(_ => {
      this.initGraph();
    });
  },
  created() {
    this.getLabels();
    this.getRecommendLabels();
  },
  methods: {
    radioClick(m) {
      this.uploadTips = m;
    },
    btnTipsClose() {
      this.tipsShow = false;
    },
    showCypher() {
      this.cypherTextShow = !this.cypherTextShow;
    },
    cypherJson() {
      if (this.graph.nodes.length == 0 && this.graph.links.length == 0) {
        this.$message.error("请先选择领域或者执行cypher");
        return;
      }
      this.jsonShow = !this.jsonShow;
      let json = this.graph;
      let options = {
        collapsed: false, //收缩所有节点
        withQuotes: false //为key添加双引号
      };
      $("#json-renderer").JSONView(json, options);
    },
    cypherRun() {
      if (this.cypherText == "") {
        this.$message.error("请输入cypher语句");
        return;
      }
      let data = { cypher: this.cypherText };
      kgBuilderApi.getCypherResult(data).then(response => {
        if (response.code == 200) {
          if (response.data) {
            this.graph.nodes = response.data.node;
            this.graph.links = response.data.relationship;
            this.updateGraph();
          } else {
            this.$message.error("暂时没有更多数据");
          }
        }
      });
    },
    initEditor() {
      if (this.editor != null) return;
      let E = window.wangEditor;
      this.editor = new E(this.$refs.editorToolbar, this.$refs.editorContent);
      this.editor.customConfig.onchange = function(html) {
        this.editorContent = html;
      };
      let token = $("meta[name='_csrf']").attr("content");
      let header = $("meta[name='_csrf_header']").attr("content");
      let str = '{ "' + header + '": "' + token + '"}';
      let headers = eval("(" + str + ")");
      this.editor.customConfig.uploadFileName = "file";
      this.editor.customConfig.uploadImgHeaders = headers;
      this.editor.customConfig.uploadImgServer = "/qiniu/upload"; // 上传图片到服务器
      this.editor.customConfig.uploadImgHooks = {
        // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式，可使用该配置
        // （但是，服务器端返回的必须是一个 JSON 格式字符串！！！否则会报错）
        customInsert: function(insertImg, res, editor) {
          // 图片上传并返回结果，自定义插入图片的事件（而不是编辑器自动插入图片！！！）
          // insertImg 是插入图片的函数，editor 是编辑器对象，result 是服务器端返回的结果
          for (let i = 0; i < res.results.length; i++) {
            let fileItem = res.results[i];
            insertImg(fileItem.url);
          }
        }
      };
      this.editor.create();
    },
    initNodeContent() {
      let data = { domainId: this.domainId, nodeId: this.selectNodeId };
      kgBuilderApi.getNodeContent(data).then(response => {
        if (response.code == 200) {
          if (response.data) {
            this.editorContent = response.data.Content;
            editor.txt.html(response.data.Content);
          } else {
            this.$message.warning("暂时没有更多数据");
          }
        }
      });
    },
    initNodeImage() {
      let data = { domainId: this.domainId, nodeId: this.selectNodeId };
      kgBuilderApi.getNodeImage(data).then(response => {
        if (response.code == 200) {
          if (response.data) {
            for (let i = 0; i < response.data.length; i++) {
              this.nodeImageList.push({
                fileUrl: response.data[i].fileName,
                imageType: response.data[i].ImageType
              });
            }
          } else {
            this.$message.warning("暂时没有更多数据");
          }
        }
      });
    },
    getNodeDetail(nodeId) {
      let data = { domainId: this.domainId, nodeId: nodeId };
      kgBuilderApi.getNodeDetail(data).then(result => {
        if (result.code == 200) {
          if (result.data) {
            this.editorContent = result.data.content;
            this.showImageList = result.data.imageList;
          } else {
            this.$message.warning("暂时没有更多数据");
          }
        }
      });
    },
    saveNodeImage() {
      let data = {
        domainId: this.domainId,
        nodeId: this.selectNodeId,
        imageList: JSON.stringify(this.nodeImageList)
      };
      kgBuilderApi.saveNodeImage(JSON.stringify(data)).then(result => {
        if (result.code == 200) {
          this.$message({
            message: "操作成功",
            type: "success"
          });
        }
      });
    },
    saveNodeContent() {
      let data = {
        domainId: this.domainId,
        nodeId: this.selectNodeId,
        content: this.editorContent
      };
      kgBuilderApi.saveNodeContent(JSON.stringify(data)).then(result => {
        if (result.code == 200) {
          this.$message({ message: "操作成功", type: "success" });
        }
      });
    },
    handlePictureCardPreview(item) {
      this.dialogImageUrl = this.imageUrlFormat(item);
      this.dialogImageVisible = true;
    },
    addNetImage() {
      if (this.netImageUrl != "") {
        this.nodeImageList.push({ file: this.netImageUrl, imageType: 1 });
        this.netImageUrl = "";
      }
    },
    imageHandleRemove(url) {
      this.nodeImageList.splice(this.nodeImageList.indexOf(url), 1);
    },
    imageUrlFormat(item) {
      return item.fileUrl;
    },
    dbImageUrlFormat(item) {
      return item.fileName;
    },
    uploadSuccess(res, file) {
      if (res.success == 1) {
        for (let i = 0; i < res.results.length; i++) {
          let fileItem = res.results[i];
          this.nodeImageList.push({ fileUrl: fileItem.url });
        }
      } else {
        this.$message.error(res.msg);
      }
    },
    propHandleClick(tab, event) {
      if (tab.name == "richTextEdit") {
        this.editorContent = "";
        this.initNodeContent();
        this.initEditor();
      }
      if (tab.name == "propImage") {
        this.nodeImageList = [];
        this.initNodeImage();
      }
    },
    operateNameFormat() {
      if (this.operateType == 1) {
        return "添加同级";
      } else if (this.operateType == 2) {
        return "添加下级";
      } else if (this.operateType == 3) {
        return "批量添加";
      }
    },
    requestFullScreen() {
      let element = document.getElementById("graphcontainerdiv");
      let width = window.screen.width;
      let height = window.screen.height;
      this.svg.attr("width", width);
      this.svg.attr("height", height);
      if (element.requestFullscreen) {
        element.requestFullscreen();
      }
      // FireFox
      else if (element.mozRequestFullScreen) {
        element.mozRequestFullScreen();
      }
      // Chrome等
      else if (element.webkitRequestFullScreen) {
        element.webkitRequestFullScreen();
      }
      // IE11
      else if (element.msRequestFullscreen) {
        element.msRequestFullscreen();
      }
    },
    getDomainGraph() {
      this.loading = true;
      let data = {
        domain: this.domain,
        nodeName: this.nodeName,
        pageSize: this.pageSize
      };
      kgBuilderApi.getDomainGraph(data).then(result => {
        if (result.code == 200) {
          if (result.data != null) {
            this.graph.nodes = result.data.node;
            this.graph.links = result.data.relationship;
            this.updateGraph();
          }
        }
      });
    },
    getCurrentNodeInfo(node) {
      let data = { domain: this.domain, nodeId: node.uuid };
      kgBuilderApi.getRelationNodeCount(data).then(result => {
        if (result.code == 200) {
          this.selectNode.name = node.name;
          this.selectNode.count = result.data;
        }
      });
    },
    btnAddSingle() {
      d3.select(".graphContainer").style("cursor", "crosshair"); //进入新增模式，鼠标变成＋
    },
    btnDeleteLink() {
      this.isDeleteLink = true;
      d3.select(".link").attr("class", "link linkDelete"); // 修改鼠标样式为"+"
    },
    getMoreNode() {
      let _this=this;
      let data = { domain: this.domain, nodeId: this.selectNodeId };
      kgBuilderApi.getMoreRelationNode(data).then(result => {
        if (result.code == 200) {
          let newNodes = result.data.node;
          let newShips = result.data.relationship;
          let oldNodesCount = this.graph.nodes.length;
          newNodes.forEach(function(m) {
            let sobj = _this.graph.nodes.find(function(x) {
              return x.uuid === m.uuid;
            });
            if (typeof sobj == "undefined") {
              _this.graph.nodes.push(m);
            }
          });
          let newNodesCount = this.graph.nodes.length;
          if (newNodesCount <= oldNodesCount) {
            this.$message({
              message: "没有更多节点信息",
              type: "success"
            });
            return;
          }
          newShips.forEach(function(m) {
            let sobj = this.graph.links.find(function(x) {
              return x.uuid === m.uuid;
            });
            if (typeof sobj == "undefined") {
              this.graph.links.push(m);
            }
          });
          this.updateGraph();
        }
      });
    },
    btnAddSame() {
      this.operateType = 1;
      this.isBatchCreate = true;
      this.isEdit = false;
    },
    btnQuickAddNode() {
      this.isEdit = false;
      this.isBatchCreate = true;
      // $("#link_menubar").hide();
      this.operateType = 3;
    },
    deleteDomain(id, value) {
      this.$confirm(
        "此操作将删除该标签及其下节点和关系(不可恢复), 是否继续?",
        "三思而后行",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }
      )
        .then(function(res) {
          let data = { domainId: id, domain: value };
          kgBuilderApi.deleteDomain(data).then(result => {
            if (result.code == 200) {
              this.getLabels();
              this.domain = "";
            }
          });
        })
        .catch(function() {
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },
    createDomain(value) {
      this.$prompt("请输入领域名称", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消"
      })
        .then(function(res) {
          value = res.value;
          let data = { domain: value, type: 0 };
          kgBuilderApi.createDomain(data).then(result => {
            if (result.code == 200) {
              this.getLabels();
              this.domain = value;
              this.getDomainGraph();
            }
          });
        })
        .catch(function() {
          this.$message({
            type: "info",
            message: "取消输入"
          });
        });
    },
    getLabels() {
      let data = {};
      kgBuilderApi.getDomains(data).then(result => {
        if (result.code == 200) {
          this.pageModel = result.data;
          this.pageModel.totalPage =
            parseInt((result.data.totalCount - 1) / result.data.pageSize) + 1;
        }
      });
    },
    getRecommendLabels() {
      let data = {};
      kgBuilderApi.getDomains(data).then(result => {
        if (result.code == 200) {
          this.pageModel = result.data;
          this.pageModel.totalPage =
            parseInt((result.data.totalCount - 1) / result.data.pageSize) + 1;
        }
      });
    },
    getMoreDomain() {
      this.pageModel.pageIndex = this.pageModel.pageIndex + 1;
      let data = { pageIndex: this.pageModel.pageIndex };
      kgBuilderApi.getDomains(data).then(result => {
        if (result.code == 200) {
          this.pageModel.nodeList.push.apply(
            this.pageModel.nodeList,
            result.data.nodeList
          );
        }
      });
    },
    initGraph() {
      let graphContainer = d3.select(".graphContainer");
      let width = graphContainer._groups[0][0].offsetWidth;
      let height = window.screen.height - 154; //
      this.svg = graphContainer.append("svg");
      this.svg.attr("width", width);
      this.svg.attr("height", height);
      this.simulation = d3
        .forceSimulation()
        .force(
          "link",
          d3
            .forceLink()
            .distance(function(d) {
              return Math.floor(Math.random() * (700 - 200)) + 200;
            })
            .id(function(d) {
              return d.uuid;
            })
        )
        .force("charge", d3.forceManyBody().strength(-400))
        .force("collide", d3.forceCollide())
        .force("center", d3.forceCenter(width / 2, (height - 200) / 2));
      this.linkGroup = this.svg.append("g").attr("class", "line");
      this.linkTextGroup = this.svg.append("g").attr("class", "lineText");
      this.nodeGroup = this.svg.append("g").attr("class", "node");
      this.nodeTextGroup = this.svg.append("g").attr("class", "nodeText");
      this.nodeSymbolGroup = this.svg.append("g").attr("class", "nodeSymbol");
      this.nodeButtonGroup = this.svg.append("g").attr("class", "nodeButton");
      this.addMaker();
      this.tooltip = this.svg.append("div").style("opacity", 0);
      this.svg.on(
        "click",
        function() {
          d3.selectAll(".buttongroup").classed("circle_operate", true);
        },
        "false"
      );
    },
    updateGraph() {
      let lks = this.graph.links;
      let nodes = this.graph.nodes;
      let links = [];
      //由后端传过来的节点坐标，固定节点，由于是字符串，需要转换
      nodes.forEach(function(n) {
        if (typeof n.fx == "undefined" || n.fx == "" || n.fx == null) {
          n.fx = null;
        }
        if (typeof n.fy == "undefined" || n.fy == "" || n.fy == null) {
          n.fy = null;
        }
        if (typeof n.fx == "string") n.fx = parseFloat(n.fx);
        if (typeof n.fy == "string") n.fy = parseFloat(n.fy);
      });
      lks.forEach(function(m) {
        let sourceNode = nodes.filter(function(n) {
          return n.uuid === m.sourceId;
        })[0];
        if (typeof sourceNode == "undefined") return;
        let targetNode = nodes.filter(function(n) {
          return n.uuid === m.targetId;
        })[0];
        if (typeof targetNode == "undefined") return;
        links.push({ source: sourceNode.uuid, target: targetNode.uuid, lk: m });
      });
      //为每一个节点定制按钮组
      this.addNodeButton();
      if (links.length > 0) {
        _.each(links, function(link) {
          let same = _.filter(links, {
            source: link.source,
            target: link.target
          });
          let sameAlt = _.filter(links, {
            source: link.target,
            target: link.source
          });
          let sameAll = same.concat(sameAlt);
          _.each(sameAll, function(s, i) {
            s.sameIndex = i + 1;
            s.sameTotal = sameAll.length;
            s.sameTotalHalf = s.sameTotal / 2;
            s.sameUneven = s.sameTotal % 2 !== 0;
            s.sameMiddleLink =
              s.sameUneven === true &&
              Math.ceil(s.sameTotalHalf) === s.sameIndex;
            s.sameLowerHalf = s.sameIndex <= s.sameTotalHalf;
            s.sameArcDirection = 1;
            //s.sameArcDirection = s.sameLowerHalf ? 0 : 1;
            s.sameIndexCorrected = s.sameLowerHalf
              ? s.sameIndex
              : s.sameIndex - Math.ceil(s.sameTotalHalf);
          });
        });
        let maxSame = _.chain(links)
          .sortBy(function(x) {
            return x.sameTotal;
          })
          .last()
          .value().sameTotal;

        _.each(links, function(link) {
          link.maxSameHalf = Math.round(maxSame / 2);
        });
      }
      // 更新连线 links
      let link = this.linkGroup
        .selectAll(".line >path")
        .data(links, function(d) {
          return d.uuid;
        });
      link.exit().remove();
      let linkEnter = this.drawLink(link);
      link = linkEnter.merge(link);
      // 更新连线文字
      this.linkTextGroup
        .selectAll("text")
        .data(links, function(d) {
          return d.uuid;
        })
        .exit()
        .remove(); //移除多余的text dom
      let linktext = this.linkTextGroup
        .selectAll("text >textPath")
        .data(links, function(d) {
          return d.uuid;
        });
      linktext.exit().remove();
      let linkTextEnter = this.drawLinkText(linktext);
      linktext = linkTextEnter.merge(linktext).text(function(d) {
        return d.lk.name;
      });
      // 更新节点按钮组
      d3.selectAll(".nodeButton >g").remove();
      let nodeButton = this.nodeButtonGroup
        .selectAll(".nodeButton")
        .data(nodes, function(d) {
          return d;
        });
      nodeButton.exit().remove();
      let nodeButtonEnter = this.drawNodeButton(nodeButton);
      nodeButton = nodeButtonEnter.merge(nodeButton);
      // 更新节点
      let node = this.nodeGroup.selectAll("circle").data(nodes, function(d) {
        return d.uuid;
      });
      node.exit().remove();
      let nodeEnter = this.drawNode(node);
      node = nodeEnter.merge(node).text(function(d) {
        return d.name;
      });
      // 更新节点文字
      let nodeText = this.nodeTextGroup
        .selectAll("text")
        .data(nodes, function(d) {
          return d.uuid;
        });
      nodeText.exit().remove();
      let nodeTextEnter = this.drawNodeText(nodeText);
      nodeText = nodeTextEnter.merge(nodeText).text(function(d) {
        return d.name;
      });
      nodeText
        .append("title") // 为每个节点设置title
        .text(function(d) {
          return d.name;
        });
      // 更新节点标识
      let nodeSymbol = this.nodeSymbolGroup
        .selectAll("path")
        .data(nodes, function(d) {
          return d.uuid;
        });
      nodeSymbol.exit().remove();
      let nodeSymbolEnter = this.drawNodeSymbol(nodeSymbol);
      nodeSymbol = nodeSymbolEnter.merge(nodeSymbol);
      nodeSymbol.attr("fill", "#e15500");
      nodeSymbol.attr("display", function(d) {
        if (typeof d.hasFile != "undefined" && d.hasFile > 0) {
          return "block";
        }
        return "none";
      });
      this.simulation.nodes(nodes).on("tick", ticked);
      this.simulation.force("link").links(links);
      this.simulation.alphaTarget(1).restart();
      function linkArc(d) {
        let dx = d.target.x - d.source.x,
          dy = d.target.y - d.source.y,
          dr = Math.sqrt(dx * dx + dy * dy),
          unevenCorrection = d.sameUneven ? 0 : 0.5;
        let curvature = 2,
          arc =
            (1.0 / curvature) *
            ((dr * d.maxSameHalf) / (d.sameIndexCorrected - unevenCorrection));
        if (d.sameMiddleLink) {
          arc = 0;
        }
        let dd =
          "M" +
          d.source.x +
          "," +
          d.source.y +
          "A" +
          arc +
          "," +
          arc +
          " 0 0," +
          d.sameArcDirection +
          " " +
          d.target.x +
          "," +
          d.target.y;
        return dd;
      }

      function ticked() {
        link.attr("d", linkArc);
        // 更新节点坐标
        node
          .attr("cx", function(d) {
            return d.x;
          })
          .attr("cy", function(d) {
            return d.y;
          });
        // 更新节点操作按钮组坐标
        nodeButton
          .attr("cx", function(d) {
            return d.x;
          })
          .attr("cy", function(d) {
            return d.y;
          });
        nodeButton.attr("transform", function(d) {
          return "translate(" + d.x + "," + d.y + ") scale(1)";
        });

        // 更新文字坐标
        nodeText
          .attr("x", function(d) {
            return d.x;
          })
          .attr("y", function(d) {
            return d.y;
          });
        // 更新回形针坐标
        nodeSymbol.attr("transform", function(d) {
          return (
            "translate(" + (d.x + 8) + "," + (d.y - 30) + ") scale(0.015,0.015)"
          );
        });
      }
      // 鼠标滚轮缩放
      //this.svg.call(d3.zoom().transform, d3.zoomIdentity);//缩放至初始倍数
      this.svg.call(
        d3.zoom().on("zoom", function() {
          d3.select("#link_menubar").style("display", "none");
          d3.select("#nodeDetail").style("display", "none");
          d3.selectAll(".node").attr("transform", d3.event.transform);
          d3.selectAll(".nodeText").attr("transform", d3.event.transform);
          d3.selectAll(".line").attr("transform", d3.event.transform);
          d3.selectAll(".lineText").attr("transform", d3.event.transform);
          d3.selectAll(".nodeSymbol").attr("transform", d3.event.transform);
          d3.selectAll(".nodeButton").attr("transform", d3.event.transform);
          //this.svg.selectAll("g").attr("transform", d3.event.transform);
        })
      );
      this.svg.on("dblclick.zoom", null); // 静止双击缩放
      //按钮组事件
      let _this = this;
      this.svg.selectAll(".buttongroup").on("click", function(d, i) {
        if (_this.nodeButtonAction) {
          switch (_this.nodeButtonAction) {
            case "EDIT":
              _this.isEdit = true;
              _this.propActiveName = "propEdit";
              _this.txx = d.x;
              _this.tyy = d.y;
              break;
            case "MORE":
              _this.getMoreNode();
              break;
            case "CHILD":
              _this.operateType = 2;
              _this.isBatchCreate = true;
              _this.isEdit = false;
              break;
            case "LINK":
              _this.isAddLink = true;
              _this.selectSourceNodeId = d.uuid;
              break;
            case "DELETE":
              _this.selectNodeId = d.uuid;
              let out_buttongroup_id = ".out_buttongroup_" + i;
              _this.deleteNode(out_buttongroup_id);
              break;
          }
          //ACTION = '';//重置 ACTION
        }
      });
      //按钮组事件绑定
      this.svg.selectAll(".action_0").on("click", function(d) {
        _this.nodeButtonAction = "EDIT";
      });
      this.svg.selectAll(".action_1").on("click", function(d) {
        _this.nodeButtonAction = "MORE";
      });
      this.svg.selectAll(".action_2").on("click", function(d) {
        _this.nodeButtonAction = "CHILD";
      });
      this.svg.selectAll(".action_3").on("click", function(d) {
        _this.nodeButtonAction = "LINK";
      });
      this.svg.selectAll(".action_4").on("click", function(d) {
        _this.nodeButtonAction = "DELETE";
      });
    },
    createNode() {
      let data = this.graphNode;
      data.domain = this.domain;
      kgBuilderApi.createNode(data).then(result => {
        if (result.code == 200) {
          if (this.graphNode.uuid != 0) {
            for (let i = 0; i < this.graph.nodes.length; i++) {
              if (this.graph.nodes[i].uuid == this.graphNode.uuid) {
                this.graph.nodes.splice(i, 1);
              }
            }
          }
          let newNode = result.data;
          newNode.x = this.txx;
          newNode.y = this.tyy;
          newNode.fx = this.txx;
          newNode.fy = this.tyy;
          this.graph.nodes.push(newNode);
          this.resetNode();
          this.updateGraph();
          this.isEdit = false;
          this.resetSubmit();
        }
      });
    },
    createSingleNode() {
      let data = { name: "", r: 30 };
      data.domain = this.domain;
      kgBuilderApi.createNode(data).then(result => {
        if (result.code == 200) {
          d3.select(".graphContainer").style("cursor", "");
          let newNode = result.data;
          newNode.x = this.txx;
          newNode.y = this.tyy;
          newNode.fx = this.txx;
          newNode.fy = this.tyy;
          this.graph.nodes.push(newNode);
          this.updateGraph();
        }
      });
    },
    addMaker() {
      let arrowMarker = this.svg
        .append("marker")
        .attr("id", "arrow")
        .attr("markerUnits", "strokeWidth")
        .attr("markerWidth", "20") //
        .attr("markerHeight", "20")
        .attr("viewBox", "0 -5 10 10")
        .attr("refX", "22") // 13
        .attr("refY", "0")
        .attr("orient", "auto");
      let arrow_path = "M0,-5L10,0L0,5"; // 定义箭头形状
      arrowMarker
        .append("path")
        .attr("d", arrow_path)
        .attr("fill", "#fce6d4");
    },
    addNodeButton(r) {
      //先删除所有为节点自定义的按钮组
      d3.selectAll("svg >defs").remove();
      let nodes = this.graph.nodes;
      let database = [1, 1, 1, 1, 1];
      let pie = d3.pie();
      let piedata = pie(database);
      let nodeButton = this.svg.append("defs");
      nodes.forEach(function(m) {
        let nBtng = nodeButton.append("g").attr("id", "out_circle" + m.uuid); //为每一个节点定制一个按钮组，在画按钮组的时候为其指定该id
        let buttonEnter = nBtng
          .selectAll(".buttongroup")
          .data(piedata)
          .enter()
          .append("g")
          .attr("class", function(d, i) {
            return "action_" + i;
          });
        let defaultR = 30;
        if (typeof m.r == "undefined") {
          m.r = defaultR;
        }
        let arc = d3
          .arc()
          .innerRadius(m.r)
          .outerRadius(m.r + 30);
        buttonEnter
          .append("path")
          .attr("d", function(d) {
            return arc(d);
          })
          .attr("fill", "#D2D5DA")
          .style("opacity", 0.6)
          .attr("stroke", "#f0f0f4")
          .attr("stroke-width", 2);
        buttonEnter
          .append("text")
          .attr("transform", function(d, i) {
            return "translate(" + arc.centroid(d) + ")";
          })
          .attr("text-anchor", "middle")
          .text(function(d, i) {
            let zi = new Array();
            zi[0] = "编辑";
            zi[1] = "展开";
            zi[2] = "追加";
            zi[3] = "连线";
            zi[4] = "删除";
            return zi[i];
          })
          .attr("font-size", 10);
      });
    },
    dragStarted(d) {
      if (!d3.event.active) this.simulation.alphaTarget(0.3).restart();
      d.fx = d.x;
      d.fy = d.y;
      d.fixed = true;
    },
    dragged(d) {
      d.fx = d3.event.x;
      d.fy = d3.event.y;
    },
    dragEnded(d) {
      if (!d3.event.active) this.simulation.alphaTarget(0);
      d.fx = d3.event.x;
      d.fy = d3.event.y;
      let domain = this.domain;
      let uuid = d.uuid;
      let fx = d.fx;
      let fy = d.fy;
      let data = { domain: domain, uuid: uuid, fx: fx, fy: fy };
      kgBuilderApi.updateCoordinateOfNode(data).then(result => {});
    },
    drawNode(node) {
      let _this = this;
      let nodeEnter = node.enter().append("circle");
      nodeEnter.attr("r", function(d) {
        if (typeof d.r != "undefined" && d.r != "") {
          return d.r;
        }
        return 30;
      });
      nodeEnter.attr("fill", function(d) {
        if (typeof d.color != "undefined" && d.color != "") {
          return d.color;
        }
        return "#ff4500";
      });
      //nodeEnter.style("opacity", 0.8);
      nodeEnter.style("opacity", 1);
      nodeEnter.style("stroke", function(d) {
        if (typeof d.color != "undefined" && d.color != "") {
          return d.color;
        }
        return "#ff4500";
      });
      nodeEnter.style("stroke-opacity", 0.6);
      nodeEnter
        .append("title") // 为每个节点设置title
        .text(function(d) {
          return d.name;
        });
      nodeEnter.on("mouseover", function(d, i) {
        _this.nodeDetail = d;
        _this.timer = setTimeout(function() {
          d3.select("#richContainer")
            .style("position", "absolute")
            .style("left", d.x + "px")
            .style("top", d.y + "px")
            .style("display", "block");
          _this.editorContent = "";
          _this.showImageList = [];
          _this.getNodeDetail(d.uuid);
        }, 2000);
      });
      nodeEnter.on("mouseout", function(d, i) {
        clearTimeout(_this.timer);
      });
      nodeEnter.on("dblclick", function(d) {
        _this.updateNodeName(d); // 双击更新节点名称
      });
      nodeEnter.on("mouseenter", function(d) {
        let aa = d3.select(this)._groups[0][0];
        if (aa.classList.contains("selected")) return;
        d3.select(this).style("stroke-width", "6");
      });
      nodeEnter.on("mouseleave", function(d) {
        let aa = d3.select(this)._groups[0][0];
        if (aa.classList.contains("selected")) return;
        d3.select(this).style("stroke-width", "2");
      });
      nodeEnter.on("click", function(d, i) {
        d3.select("#nodeDetail").style("display", "block");
        let out_buttongroup_id = ".out_buttongroup_" + i;
        _this.svg.selectAll(".buttongroup").classed("circle_operate", true);
        _this.svg
          .selectAll(out_buttongroup_id)
          .classed("circle_operate", false);
        _this.graphNode = d;
        _this.selectNodeId = d.uuid;
        _this.selectNodeName = d.name;
        // 添加连线状态
        if (_this.isAddLink) {
          _this.selectTargetNodeId = d.uuid;
          if (
            _this.selectSourceNodeId == _this.selectTargetNodeId ||
            _this.selectSourceNodeId == 0 ||
            _this.selectTargetNodeId == 0
          )
            return;
          _this.createLink(
            _this.selectSourceNodeId,
            _this.selectTargetNodeId,
            "RE"
          );
          _this.selectSourceNodeId = 0;
          _this.selectTargetNodeId = 0;
          d.fixed = false;
          d3.event.stopPropagation();
          d3.event.preventDefault();
        }
      });
      nodeEnter.call(
        d3
          .drag()
          .on("start", this.dragStarted)
          .on("drag", this.dragged)
          .on("end", this.dragEnded)
      );
      return nodeEnter;
    },
    drawNodeText(nodeText) {
      let _this = this;
      let nodeTextEnter = nodeText
        .enter()
        .append("text")
        .style("fill", "#fff")
        .attr("dy", 4)
        .attr("font-family", "微软雅黑")
        .attr("text-anchor", "middle")
        .text(function(d) {
          if (typeof d.name == "undefined") return "";
          let length = d.name.length;
          if (d.name.length > 4) {
            let s = d.name.slice(0, 4) + "...";
            return s;
          }
          return d.name;
        });
      nodeTextEnter.on("mouseover", function(d, i) {
        this.timer = setTimeout(function() {
          d3.select("#richContainer")
            .style("position", "absolute")
            .style("left", d.x + "px")
            .style("top", d.y + "px")
            .style("display", "block");
          _this.editorContent = "";
          _this.showImageList = [];
          _this.getNodeDetail(d.uuid);
        }, 3000);
      });

      nodeTextEnter.on("dblclick", function(d) {
        _this.updateNodeName(d); // 双击更新节点名称
      });
      nodeTextEnter.on("click", function(d) {
        $("#link_menubar").hide(); // 隐藏空白处右键菜单
        _this.graphNode = d;
        _this.selectNodeId = d.uuid;
        // 更新工具栏节点信息
        _this.getCurrentNodeInfo(d);
        // 添加连线状态
        if (_this.isAddLink) {
          _this.selectTargetNodeId = d.uuid;
          if (
            _this.selectSourceNodeId == this.selectTargetNodeId ||
            _this.selectSourceNodeId == 0 ||
            _this.selectTargetNodeId == 0
          )
            return;
          _this.createLink(
            _this.selectSourceNodeId,
            _this.selectTargetNodeId,
            "RE"
          );
          _this.selectSourceNodeId = 0;
          _this.selectTargetNodeId = 0;
          d.fixed = false;
          d3.event.stopPropagation();
        }
      });

      return nodeTextEnter;
    },
    drawNodeSymbol(nodeSymbol) {
      let symbol_path =
        "M566.92736 550.580907c30.907733-34.655573 25.862827-82.445653 25.862827-104.239787 0-108.086613-87.620267-195.805867-195.577173-195.805867-49.015467 0-93.310293 18.752853-127.68256 48.564907l-0.518827-0.484693-4.980053 4.97664c-1.744213 1.64864-3.91168 2.942293-5.59104 4.72064l0.515413 0.484693-134.69696 133.727573L216.439467 534.8352l0 0 137.478827-136.31488c11.605333-10.410667 26.514773-17.298773 43.165013-17.298773 36.051627 0 65.184427 29.197653 65.184427 65.24928 0 14.032213-5.33504 26.125653-12.73856 36.829867l-131.754667 132.594347 0.515413 0.518827c-10.31168 11.578027-17.07008 26.381653-17.07008 43.066027 0 36.082347 29.16352 65.245867 65.184427 65.245867 16.684373 0 31.460693-6.724267 43.035307-17.07008l0.515413 0.512M1010.336427 343.49056c0-180.25472-145.882453-326.331733-325.911893-326.331733-80.704853 0-153.77408 30.22848-210.418347 79.0528l0.484693 0.64512c-12.352853 11.834027-20.241067 28.388693-20.241067 46.916267 0 36.051627 29.16352 65.245867 65.211733 65.245867 15.909547 0 29.876907-6.36928 41.192107-15.844693l0.38912 0.259413c33.624747-28.030293 76.301653-45.58848 123.511467-45.58848 107.99104 0 195.549867 87.6544 195.549867 195.744427 0 59.815253-27.357867 112.71168-69.51936 148.503893l0 0-319.25248 317.928107 0 0c-35.826347 42.2912-88.654507 69.710507-148.340053 69.710507-107.956907 0-195.549867-87.68512-195.549867-195.805867 0-59.753813 27.385173-112.646827 69.515947-148.43904l-92.18048-92.310187c-65.69984 59.559253-107.700907 144.913067-107.700907 240.749227 0 180.28544 145.885867 326.301013 325.915307 326.301013 95.218347 0 180.02944-41.642667 239.581867-106.827093l0.13312 0.129707 321.061547-319.962453-0.126293-0.13312C968.69376 523.615573 1010.336427 438.71232 1010.336427 343.49056L1010.336427 343.49056 1010.336427 343.49056zM1010.336427 343.49056"; // 定义回形针形状
      let nodeSymbolEnter = nodeSymbol
        .enter()
        .append("path")
        .attr("d", symbol_path);
      nodeSymbolEnter.call(
        d3
          .drag()
          .on("start", this.dragStarted)
          .on("drag", this.dragged)
          .on("end", this.dragEnded)
      );
      return nodeSymbolEnter;
    },
    drawNodeButton(nodeButton) {
      let nodeButtonEnter = nodeButton
        .enter()
        .append("g")
        .append("use") //  为每个节点组添加一个 use 子元素
        .attr("r", function(d) {
          return d.r;
        })
        .attr("xlink:href", function(d) {
          return "#out_circle" + d.uuid;
        }) //  指定 use 引用的内容
        .attr("class", function(d, i) {
          return "buttongroup out_buttongroup_" + i;
        })
        .classed("circle_operate", true);

      return nodeButtonEnter;
    },
    drawLink(link) {
      let _this = this;
      let linkEnter = link
        .enter()
        .append("path")
        .attr("stroke-width", 1)
        .attr("stroke", "#fce6d4")
        .attr("fill", "none")
        .attr("id", function(d) {
          return (
            "invis_" + d.lk.sourceId + "-" + d.lk.name + "-" + d.lk.targetId
          );
        })
        .attr("marker-end", "url(#arrow)"); // 箭头
      linkEnter.on("dblclick", function(d) {
        _this.selectNodeId = d.lk.uuid;
        if (_this.isDeleteLink) {
          _this.deleteLink();
        } else {
          _this.updateLinkName();
        }
      });
      linkEnter.on("contextmenu", function(d,p,x,z) {
        let dd = d3.mouse(this);
        _this.selectNodeId = d.lk.uuid;
        _this.selectlinkname = d.lk.name;
          let link={
            left:dd[0] + "px",
            top:dd[1] + "px",
            show:true
          }
          _this.$refs.menu_link.init(link);
         d3.event.preventDefault(); // 禁止系统默认右键
         d3.event.stopPropagation(); // 禁止空白处右键
      });
      linkEnter.on("mouseenter", function(d) {
        d3.select(this)
          .style("stroke-width", "6")
          .attr("stroke", "#ff9e9e")
          .attr("marker-end", "url(#arrow)");
        _this.nodeDetail = d.lk;
        d3.select("#nodeDetail").style("display", "block");
      });
      linkEnter.on("mouseleave", function(d) {
        d3.select(this)
          .style("stroke-width", "1")
          .attr("stroke", "#fce6d4")
          .attr("marker-end", "url(#arrow)");
      });
      return linkEnter;
    },
    drawLinkText(link) {
      let linkTextEnter = link
        .enter()
        .append("text")
        .style("fill", "#e3af85")
        .append("textPath")
        .attr("startOffset", "50%")
        .attr("text-anchor", "middle")
        .attr("xlink:href", function(d) {
          return (
            "#invis_" + d.lk.sourceId + "-" + d.lk.name + "-" + d.lk.targetId
          );
        })
        .style("font-size", 14)
        .text(function(d) {
          if (d.lk.name != "") {
            return d.lk.name;
          }
        });

      linkTextEnter.on("mouseover", function(d) {
        app.selectNodeId = d.lk.uuid;
        app.selectlinkname = d.lk.name;
        let cc = $(this).offset();
        d3.select("#link_menubar")
          .style("position", "absolute")
          .style("left", cc.left + "px")
          .style("top", cc.top + "px")
          .style("display", "block");
      });
      return linkTextEnter;
    },
    deleteNode(out_buttongroup_id) {
      let _this=this;
      _this.$confirm(
        "此操作将删除该节点及周边关系(不可恢复), 是否继续?",
        "三思而后行",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }
      )
        .then(function() {
          let data = { domain: _this.domain, nodeId: _this.selectNodeId };
          kgBuilderApi.deleteNode(data).then(result => {
            if (result.code == 200) {
              _this.svg.selectAll(out_buttongroup_id).remove();
              let rShips = result.data;
              // 删除节点对应的关系
              for (let m = 0; m < rShips.length; m++) {
                for (let i = 0; i < _this.graph.links.length; i++) {
                  if (_this.graph.links[i].uuid == rShips[m].uuid) {
                    _this.graph.links.splice(i, 1);
                    i = i - 1;
                  }
                }
              }
              // 找到对应的节点索引
              let j = -1;
              for (let i = 0; i < _this.graph.nodes.length; i++) {
                if (_this.graph.nodes[i].uuid == _this.selectNodeId) {
                  j = i;
                  break;
                }
              }
              if (j >= 0) {
                _this.selectNodeId = 0;
                _this.graph.nodes.splice(j, 1); // 根据索引删除该节点
                _this.updateGraph();
                _this.resetNode();
                _this.$message({
                  type: "success",
                  message: "操作成功!"
                });
              }
            }
          })
        })
        .catch(function() {
          _this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },
    deleteLink() {
      this.$confirm("此操作将删除该关系(不可恢复), 是否继续?", "三思而后行", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(function() {
          let data = { domain: this.domain, shipId: this.selectNodeId };
          kgBuilderApi.deleteLink(data).then(result => {
            if (result.code == 200) {
              let j = -1;
              for (let i = 0; i < this.graph.links.length; i++) {
                if (this.graph.links[i].uuid == this.selectNodeId) {
                  j = i;
                  break;
                }
              }
              if (j >= 0) {
                this.selectNodeId = 0;
                this.graph.links.splice(i, 1);
                this.updateGraph();
                this.isDeleteLink = false;
              }
            }
          });
        })
        .catch(function() {
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });
    },
    createLink(sourceId, targetId, ship) {
      let data = {
        domain: this.domain,
        sourceId: sourceId,
        targetId: targetId,
        ship: ship
      };
      kgBuilderApi.createLink(data).then(result => {
        if (result.code == 200) {
          let newShip = result.data;
          this.graph.links.push(newShip);
          this.updateGraph();
          this.isAddLink = false;
        }
      });
    },
    updateLinkName() {
      debugger;
      let _this = this;
      this.$prompt("请输入关系名称", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputValue: this.selectlinkname
      })
        .then(function(res) {
          let value = res.value;
          let data = {
            domain: _this.domain,
            shipId: _this.selectNodeId,
            shipName: value
          };
          kgBuilderApi.updateLink(data).then(result => {
            if (result.code == 200) {
              let newShip = result.data;
              _this.graph.links.forEach(function(m) {
                if (m.uuid == newShip.uuid) {
                  m.name = newShip.name;
                }
              });
              _this.selectNodeId = 0;
              _this.updateGraph();
              _this.isAddLink = false;
              _this.selectlinkname = "";
            }
          });
        })
        .catch(function() {
          _this.$message({
            type: "info",
            message: "取消输入"
          });
        });
    },
    updateNodeName(d) {
      let _this = this;
      _this
        .$prompt("编辑节点名称", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          inputValue: d.name
        })
        .then(function(res) {
          let value = res.value;
          let data = { domain: _this.domain, nodeId: d.uuid, nodeName: value };
          kgBuilderApi.updateNodeName(data).then(result => {
            if (result.code == 200) {
              if (d.uuid != 0) {
                for (let i = 0; i < _this.graph.nodes.length; i++) {
                  if (_this.graph.nodes[i].uuid == d.uuid) {
                    _this.graph.nodes[i].name = value;
                  }
                }
              }
              _this.updateGraph();
              _this.$message({
                message: "操作成功",
                type: "success"
              });
            }
          });
        })
        .catch(function() {
          _this.$message({
            type: "info",
            message: "取消操作"
          });
        });
    },
    resetSubmit() {
      this.isAddNode = false;
      this.isEdit = false;
      this.resetNode();
      this.fieldDataList = [];
      this.dataConfigActive = "";
      this.isBatchCreate = false;
      this.selectNodeId = 0;
    },
    resetNode() {
      this.graphNode = {
        uuid: 0,
        color: "ff4500",
        name: "",
        r: 30,
        x: "",
        y: ""
      };
    },
    initForm(d) {
      this.graphNode = {
        uuid: d.uuid,
        name: d.name,
        color: d.color,
        r: d.r,
        x: d.x,
        y: d.y
      };
    },
    matchDomainGraph(domain, event) {
      this.domain = domain.name;
      this.domainId = domain.id;
      this.getDomainGraph();
    },
    refreshNode(event) {
      $(".ml-a").removeClass("cur");
      $(event.currentTarget).addClass("cur");
      this.nodeName = "";
      this.getDomainGraph();
    },
    getFilterDomain(domainList) {
      let array = [];
      for (let i = 0; i < domainList.length; i++) {
        array.push({
          value: domainList[i].label.substring(
            1,
            domainList[i].label.length - 1
          )
        });
      }
      return array;
    },
    operateCommand(command) {
      if (command === "image") {
        this.exportImage();
      }
      if (command === "import") {
        this.dialogFormVisible = true;
      }
      if (command === "export") {
        this.exportFormVisible = true;
      }
    },
    exportCsv() {
      let data = { domain: this.uploadParam.domain };
      kgBuilderApi.exportGraph(data).then(result => {
        if (result.code == 200) {
          this.exportFormVisible = false;
          window.open(result.csvUrl);
        }
      });
    },
    submitUpload() {
      this.$refs.upload.submit();
      this.dialogFormVisible = false;
    },
    csvSuccess() {
      this.$refs.upload.clearFiles();
      this.uploadParam.domain = "";
      this.$message({
        message: "正在导入中,请稍后查看",
        type: "success"
      });
    },
    exportImage() {
      /*https://html2canvas.hertzen.com/getting-started  截图js*/
      html2canvas(document.querySelector(".graphContainer")).then(function(
        canvas
      ) {
        let a = document.createElement("a");
        a.href = canvas.toDataURL("image/png"); //将画布内的信息导出为png图片数据
        let timeStamp = Date.parse(new Date());
        a.download = timeStamp; //设定下载名称
        a.click(); //点击触发下载
      });
    },
    setMatchSize(m, event) {
      for (let i = 0; i < this.pageSizeList.length; i++) {
        this.pageSizeList[i].isActive = false;
        if (this.pageSizeList[i].size == m.size) {
          this.pageSizeList[i].isActive = true;
        }
      }
      this.pageSize = m.size;
      this.getDomainGraph();
    },
    batchCreateNode() {
      let data = {
        domain: this.domain,
        sourceName: this.batchCreate.sourceNodeName,
        targetNames: this.batchCreate.targetNodeNames,
        relation: this.batchCreate.relation
      };
      let _this=this;
      kgBuilderApi.batchCreateNode(data).then(result => {
        if (result.code == 200) {
          this.isBatchCreate = false;
          let newNodes = result.data.nodes;
          let newShips = result.data.ships;
          newNodes.forEach(function(m) {
            let sobj = _this.graph.nodes.find(function(x) {
              return x.uuid === m.uuid;
            });
            if (typeof sobj == "undefined") {
              _this.graph.nodes.push(m);
            }
          });
          newShips.forEach(function(m) {
            let sobj = _this.graph.links.find(function(x) {
              return x.uuid === m.uuid;
            });
            if (typeof sobj == "undefined") {
              _this.graph.links.push(m);
            }
          });
          this.updateGraph();
          this.batchCreate.sourceNodeName = "";
          this.batchCreate.targetNodeNames = "";
          this.$message({
            message: "操作成功",
            type: "success"
          });
        }
      });
    },
    batchCreateChildNode() {
      let data = {
        domain: this.domain,
        sourceId: this.selectNodeId,
        targetNames: this.batchCreate.targetNodeNames,
        relation: this.batchCreate.relation
      };
      kgBuilderApi.batchCreateChildNode(data).then(result => {
        if (result.code == 200) {
          this.isBatchCreate = false;
          let newNodes = result.data.nodes;
          let newShips = result.data.ships;
          newNodes.forEach(function(m) {
            let sobj = this.graph.nodes.find(function(x) {
              return x.uuid === m.uuid;
            });
            if (typeof sobj == "undefined") {
              this.graph.nodes.push(m);
            }
          });
          newShips.forEach(function(m) {
            let sobj = this.graph.links.find(function(x) {
              return x.uuid === m.uuid;
            });
            if (typeof sobj == "undefined") {
              this.graph.links.push(m);
            }
          });
          this.updateGraph();
          this.batchCreate.sourceNodeName = "";
          this.batchCreate.targetNodeNames = "";
          this.$message({
            message: "操作成功",
            type: "success"
          });
        }
      });
    },
    batchCreateSameNode() {
      let data = {
        domain: this.domain,
        sourceNames: this.batchCreate.sourceNodeName
      };
      kgBuilderApi.batchCreateSameNode(data).then(result => {
        if (result.code == 200) {
          this.isBatchCreate = false;
          let newNodes = result.data;
          newNodes.forEach(function(m) {
            let sobj = this.graph.nodes.find(function(x) {
              return x.uuid === m.uuid;
            });
            if (typeof sobj == "undefined") {
              this.graph.nodes.push(m);
            }
          });
          this.updateGraph();
          this.batchCreate.sourceNodeName = "";
          this.$message({
            message: "操作成功",
            type: "success"
          });
        }
      });
    },


    initContainerRightClick(event) {
      let _this = this;
      _this.svg.selectAll(".buttongroup").classed("circle_operate", true);
      let left = event.clientX;
      let top = event.clientY;
      // debugger;
      // d3.select("#blank_menubar").style.position = "absolute";
      // d3.select("#blank_menubar").style.left = left + "px";
      // d3.select("#blank_menubar").style.top = top + "px";
      document.getElementById("blank_menubar").style.position = "absolute";
      document.getElementById("blank_menubar").style.left = left + "px";
      document.getElementById("blank_menubar").style.top = top + "px";
      d3.select("#blank_menubar").style("display", "block");
      event.preventDefault();
    },
    initContainerLeftClick(event) {
      let _this = this;
      if (event.target.tagName != "circle" && event.target.tagName != "link") {
        d3.select("#nodeDetail").style("display", "none");
      }
      if (
        !(
          event.target.id === "jsoncontainer" ||
          $(event.target).parents("#jsoncontainer").length > 0
        )
      ) {
        _this.jsonShow = false;
      }
      let cursor = document.getElementById("graphContainer").style.cursor;
      if (cursor == "crosshair") {
        d3.select(".graphContainer").style("cursor", "");
        _this.txx = event.offsetX;
        _this.tyy = event.offsetY;
        _this.createSingleNode();
      }
      event.preventDefault();
    },
    boxMousedown(event) {
      if (
        !(
          event.target.id === "linkmenubar" ||
          $(event.target).parents("#linkmenubar").length > 0
        )
      ) {
        d3.select("#link_menubar").style("display", "none");
      }
      if (
        !(
          event.target.id === "batchcreateform" ||
          $(event.target).parents("#batchcreateform").length > 0
        )
      ) {
        this.isBatchCreate = false;
      }
      if (
        !(
          event.target.id === "richContainer" ||
          $(event.target).parents("#richContainer").length > 0
        )
      ) {
        $("#richContainer").hide();
      }
      if (
        !(
          event.target.id === "nodeDetail" ||
          $(event.target).parents("#nodeDetail").length > 0
        )
      ) {
        d3.select("#nodeDetail").style("display", "none");
      }
    }
  }
};
</script>
<style>
.mind-box {
  height: calc(100vh - 85px);
  overflow: hidden;
}
.mind-l {
  width: 300px;
  float: left;
  background: #f7f9fc;
  height: 100%;
  border-right: 1px solid #d3e2ec;
}
.ml-ht {
  padding-top: 20px;
  line-height: 50px;
  font-size: 16px;
  font-weight: 400;
  text-align: center;
  color: #333;
  border-bottom: 1px solid #d3e2ec;
}
.ml-a-box {
  margin: 10px;
}
.ml-a {
  display: inline-block;
  min-width: 46px;
  line-height: 1;
  padding: 6px 8px 6px 8px;
  margin: 0 4px 5px 0;
  background: #fff;
  border: 1px solid #e3e3e3;
  box-sizing: border-box;
  transition: 0.3s;
}
.ml-a span {
  max-width: 190px;
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}
.ml-a-all {
  display: block;
  margin: 10px 10px 0;
  text-align: center;
}
.ml-a span:empty:before {
  content: "閺堫亜鎳￠崥锟�";
  color: #adadad;
}
.ml-a small {
  color: #999;
}
.ml-a:hover {
  background: #f4f4f4;
}
.ml-a.cur,
.ml-a.cur small {
  background: #156498;
  color: #fff;
}
.ml-btn-box {
  text-align: right;
  padding: 0 10px;
  margin-bottom: 20px;
}
.ml-btn {
  padding: 0 5px;
  color: #156498;
}
.mind-con {
  height: 100%;
  overflow: hidden;
  background: #fff;
  display: -webkit-flex;
  display: flex;
  flex-direction: column;
}
.mind-top {
  /* line-height: 70px;
  height: 70px; */
  padding: 0 22px;
  border-bottom: 1px solid #ededed;
}
.mt-m {
  color: #666;
  margin-right: 30px;
}
.mt-m i {
  font-size: 18px;
  color: #333;
  font-weight: 700;
  font-style: normal;
}
.mb-con .search,
.mind-top .search {
  border: 1px solid #e2e2e2;
}
.svg-a-sm {
  font-size: 14px;
  color: #156498;
  margin-right: 30px;
}
.mind-cen {
  height: calc(100% - 70px);
}
.half-auto {
  height: 40%;
}
.mind-bottom {
  height: 490px;
  box-sizing: border-box;
  border-top: 1px solid #ededed;
}
.ss-d {
  display: inline-block;
  vertical-align: middle;
  margin-right: 10px;
  border-radius: 50%;
  background: #dedede;
}
.sd {
  margin: 2px;
}
.sd-active {
  color: red !important;
}
.btn-line + .btn-line {
  margin-left: 10px;
}
.co {
  color: #ee8407 !important;
}
.a {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fl {
  float: left;
}
.fr {
  float: right;
}
.tl {
  text-align: left;
}
.pl-20 {
  padding-left: 20px;
}
text {
  cursor: pointer;
  max-width: 25px;
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}
circle {
  cursor: pointer;
}
#graphcontainerdiv {
  background: #fff;
}
.el-color-picker__panel {
  left: 812px !important;
}
.wange-toolbar {
  border: 1px solid #ccc;
}
.wangeditor-form {
  border: 1px solid #ccc;
  height: 350px;
  min-height: 340px;
}
.mind-fj-box {
  display: inline-block;
  width: 290px;
  padding: 5px;
  border: 1px solid #e6e6e6;
  box-shadow: 0 0 8px rgba(206, 205, 201, 0.38);
}
.mind-fj-p {
  color: #666;
  line-height: 24px;
  padding: 5px;
  background: rgba(255, 255, 255, 0.85);
}
.mind-carousel + .mind-fj-p .el-scrollbar__wrap {
  height: auto;
  max-height: 220px;
  min-height: 0;
}
.carous-img {
  height: 100%;
  background: rgba(0, 0, 0, 0.1);
  line-height: 197px;
  text-align: center;
}
.carous-img img {
  max-width: 100%;
  max-height: 100%;
  line-height: 197px;
  vertical-align: middle;
}

.node_detail {
  position: absolute;
  width: 100%;
  line-height: 35px;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  font-size: 12px;
  padding-bottom: 10px;
  background: rgba(198, 226, 255, 0.2);
  display: none;
}
.node_pd {
  padding: 4px;
  font-size: 13px;
  font-family: -webkit-body;
  font-weight: 600;
}
.operatetips {
  position: absolute;
  right: 10px;
  float: right;
  top: 0;
  width: 335px;
  padding: 30px;
  border: 2px #ee7942 solid;
  border-radius: 4px;
}
.jsoncontainer {
  position: absolute;
  right: 30%;
  float: right;
  top: 0;
  width: 60%;
  height: 60%;
  padding: 30px;
  border: 2px #ee7942 solid;
  border-radius: 4px;
  background: #fff;
}
.cypher_toolbar {
  line-height: 70px;
  height: 85px;
  padding: 0 22px;
  border-bottom: 1px solid #ededed;
}
.hometitle {
  font-size: 18px;
  color: #282828;
  font-weight: 600;
  margin: 0;
  text-transform: uppercase;
  padding-bottom: 15px;
  margin-bottom: 25px;
  position: relative;
}
.guanzhu ul li {
  font-size: 12px;
  margin-bottom: 10px;
  background: #fff;
  color: #525252;
  line-height: 40px;
  border: 1px solid #ddd;
  border-radius: 2px;
  position: relative;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.guanzhu .wx img {
  width: 100%;
}
.el-scrollbar {
  overflow: hidden;
  position: relative;
}
ul {
  padding: 0px;
}
.icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
.el-button {
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #fff;
  border: 1px solid #d8dce5;
  color: #5a5e66;
  -webkit-appearance: none;
  text-align: center;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  outline: 0;
  margin: 0;
  -webkit-transition: 0.1s;
  transition: 0.1s;
  font-weight: 500;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;
}
.search {
  position: relative;
  width: 220px;
  height: 32px;
  border-radius: 32px;
  overflow: hidden;
}
.search .el-input__inner {
  box-sizing: border-box;
  padding-left: 15px;
  height: 32px;
  line-height: 32px;
  padding-right: 40px;
  background: transparent;
  border-radius: 32px;
  border: none;
  transition: background 0.3s;
}
.search .el-button--default {
  position: absolute;
  right: 1px;
  float: right;
  padding: 0 10px;
  font-size: 22px;
  line-height: 29px;
  color: #7c9cb2;
  background: transparent;
  border: none;
  z-index: 1;
}
.search .el-input__inner:focus {
}
.search .el-button--default:hover {
  color: #156498;
  background: transparent;
  border: none;
}
.top .search {
  margin-left: 30px;
  background: rgba(0, 0, 0, 0.25);
  display: none;
}
.circle_operate {
  display: none;
}
</style>
